﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBaseUtils.h"

namespace gnuf {
    
    class GNUF_BASE_EXPORT Sprite final
    {
    public:

        /*
            No Sprite:  _______________________________
                       | Pi = 3.1415926                |
                       |_______________________________|
        ——————————————————————————————————————————————————————————————————————————————————
            Sprite:      ____________________________________________
                        /                                            \
                       (  The Pi's value is wrong! Please try again.  ) ← Sprite Hint
                        \________   _________________________________/
                    * * * * * * *\ /* * * * * * * * * * * *
                    *   __________V____________________   *
                    *  | Pi = 3.18                     |  * ← Sprite Flag
                    *  |_______________________________|  *
                    *                                     *
                    * * * * * * * * * * * * * * * * * * * *
        */

        struct GNUF_BASE_EXPORT Flag
        {
            bool    visible = false;                                // hide, by default
            Color   color   = { 255, 0, 0, 255 };                   // red, by default

            Flag();
            Flag(const Sprite::Flag &);
            ///\return Return true, if visible.
            bool isValid() const { return this->visible; }
            bool operator==(const Sprite::Flag &) const;
            Sprite::Flag & operator=(const Sprite::Flag &);
        };
        struct GNUF_BASE_EXPORT Hint
        {
            bool            visible = false;                        // hide, by default
            Icon            icon;                                   // no icon, by default
            std::wstring    text;                                   // no text, by default
            EPlacement      placement = EPlacement::eAtTheBottom;   // show at the bottom, by default
            std::uint8_t    autoShow  = 0;                          // don't want to auto-show, by default
            std::uint8_t    autoHide  = 0;                          // don't want to auto-hide, by default

            Hint();
            Hint(const Sprite::Hint &);
            void setIcon(const EIcon);
            ///\return Return true, if the text isn't empty.
            bool isValid() const { return !this->text.empty(); }
            bool operator==(const Sprite::Hint &) const;
            Sprite::Hint & operator=(const Sprite::Hint &);
            enum class EAutoShow : std::uint8_t {
                eWhenFocusIn        = 1 << 0    ///< show, when focus in
            };
            enum class EAutoHide : std::uint8_t {
                eWhenFocusOut       = 1 << 0    ///< hide, when focus out
            };
        };
        enum class EAuthor : std::uint8_t {
            eUnknown,   ///< The author is unknown.
            eGnufItem,  ///< The author is a GnufItem, e.g. Text, Button, and etc.
            eCustomer   ///< The author is a customer.
        };
        
        explicit Sprite();
        explicit Sprite(const Sprite &);
        ~Sprite();
        
        bool operator==(const Sprite &) const;
        Sprite & operator=(const Sprite &);

        ///\brief Set the author.
        void setAuthor(Sprite::EAuthor val)     { m_author = val; }
        ///\return Return the author.
        Sprite::EAuthor author() const          { return m_author; }
        
        ///\return Retur true, if one of the flag and the hint is valid.
        bool isValid() const { return m_flag.isValid() || m_hint.isValid(); }
        
        ///\brief Set the flag.
        void setFlag(const Sprite::Flag & val)  { m_flag = val; }
        ///\return Return the flag that cannot get modified.
        const Sprite::Flag & flag() const       { return m_flag; }
        ///\return Refurn the flag reference that can get modified.
        Sprite::Flag & rFlag()                  { return m_flag; }
        
        ///\brief Set the hint.
        void setHint(const Sprite::Hint & val)  { m_hint = val; }
        ///\return Return the hint that cannot get modified.
        const Sprite::Hint & hint() const       { return m_hint; }
        ///\return Return the hint reference that can get modified.
        Sprite::Hint & rHint()                  { return m_hint; }

        ///\brief Set the auto-show.
        void set(Sprite::Hint::EAutoShow);
        ///\brief Set the auto-hide.
        void set(Sprite::Hint::EAutoHide);
        ///\return Return true if auto-show.
        bool has(Sprite::Hint::EAutoShow) const;
        ///\return Return true if auto-hide.
        bool has(Sprite::Hint::EAutoHide) const;
        
    private:
        Sprite::EAuthor m_author = Sprite::EAuthor::eUnknown;
        Sprite::Flag    m_flag;
        Sprite::Hint    m_hint;
    };
    
    class SpriteUtils
    {
    public:
        static bool modify(gcmp::OwnerPtr< Sprite > & opSprite, const Sprite & newSprite);
    };
    
}